下方程式碼片段全部都是擷取自 Secure Code Warrior 線上安全程式培訓平台,因為練習互動時的題目多半不會只有單一個檔案,可能涉及多個檔案、資料夾及多處地方修改,因此我的文章主要是針對最主要的區塊做修改及說明,若有不好理解的地方非常抱歉也還請見諒,也可以實際上去 Secure Code Warrior 玩玩看,搭配著互動,會更有感的學習哦~
SELECT * FROM Users WHERE Username = 'admin' AND Password = 'abc' OR 1=1;--
insert_user_query = "INSERT INTO users(name, age)"
VALUES (request_user_name + "," + request_user_age + ")";
insert_user = db.preapare(insert_user_query)
insert_user.execute()
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
insert_user = db.prepare "INSERT INTO user(name,age)VALUES(?, ?)"
insert_user.execure
(request_user_name, request_user_age)
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
std::string query = "INSERT INTO users( name, login, password ) VALUES(" + account->getValues() + ")";
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
和
std::string query = "SELECT COUNT(*) FROM users WHERE login = '" + account->login + "'";
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
只需將使用者登入指定為以下內容即可抹掉所有資訊:;DELETE FROM users WHERE login LIKE %'
以下SQL query,將清除“使用者”表:SELECT COUNT(*) FROM users WHERE login = '';DELETE FROM users WHERE login LIKE '%';
Database.cpp
std::string query = "INSERT INTO users( name, login, password ) VALUES(" + account->getValues() + ")";
result = PQexec( connection, query.c_str() );
if( PQresultStatus( result ) != PGRES_COMMAND_OK )
{
error( query, result );
return;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成
DBQuery dbQuery = DBQuery("INSERT INTO users( name, login, password ) VALUES( $1::varchar, $2::varchar, $3::varchar )");
dbQuery.arg( account->name ).arg( account->login ).arg( account->password );
result = dbQuery.execute( connection );
if( PQresultStatus( result ) != PGRES_COMMAND_OK )
{
error( dbQuery.get(), result );
return;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
DB.cpp
std::string query = "SELECT COUNT(*) FROM users WHERE login = '" +
account->login + "'";
PGresult* result = PQexec( connection, query.c_str() );
if( PQresultStatus( result ) != PGRES_TUPLES_OK )
{
error( query, result );
return false;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成
DBQuery dbQuery("SELECT COUNT(*) FROM users WHERE login = $1::varchar");
dbQuery.arg( account->login );
PGresult* result = dbQuery.execute( connection );
if( PQresultStatus( result ) != PGRES_TUPLES_OK )
{
error( dbQuery.get(), result );
return false;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
使用 prepared SQL語句更好,因為 prepared statements 將所有提交的使用者資料視為參數,這些參數內容不能修改 SQL request 邏輯以傷害資料庫,防止SQL注入攻擊。
std::string query = "SELECT * FROM users WHERE login = '" + login + "' AND password = '" + password +"'";
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:Account Database::getUser
中的動態SQL查詢容易被SQL注入。因為沒有限制對使用者提供的傳入資料進行檢查或消毒。
例如,只需由使用者輸入以下內容即可獲得授權並存取系統:login = "x' OR 'x' = 'x";
password = "y' OR 'y' = 'y";
把原程式碼:
std::string query = "SELECT * FROM users WHERE login = '" + login + "' AND password = '" + password +"'";
PGresult* result = PQexec( connection, query.c_str() );
if( PQresultStatus( result ) != PGRES_TUPLES_OK )
{
error( query, result );
return account;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成
DBQuery dbQuery("SELECT * FROM users WHERE login = $1::varchar AND password = $2::varchar");
dbQuery.arg( login ).arg( password );
PGresult* result = dbQuery.execute( connection );
if( PQresultStatus( result ) != PGRES_TUPLES_OK )
{
error( dbQuery.get(), result );
return account;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
總是使用 prepared SQL 語句而不是直接將使用者輸入嵌入到SQL語法中
scriptfile << "@if not exist " + fullName + " echo " + NOTFOUND;
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
作為引數傳遞的值用於建立 batch 檔的內容,執行後允許攻擊者更改正在執行的程式語法,從而執行輸入的惡意程式,這不安全。此外,該程式僅適用於Windows作業系統。
把原程式碼整段刪掉
const std::string NOTFOUND("!NOTFOUND!");
char buffer[128]{};
std::ofstream scriptfile("findMySit.bat");
scriptfile << "@if not exist " + fullName + " echo " + NOTFOUND;
scriptfile.close();
FILE* pipe = _popen("findMySit.bat", "r");
fgets(buffer, sizeof buffer, pipe);
_pclose(pipe);
if (std::equal(NOTFOUND.begin(), NOTFOUND.end(), std::begin(buffer)) == true)
return false;
std::ifstream infile(fullName);
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成
std::ifstream infile(fullName);
if (infile.good() == false)
return false;
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
建議使用標準庫的功能,而不是根據輸入的值執行程式碼或可執行的 batch 檔。使用檔案系統庫中的good()
函式,該函式執行所有必要的檢查,並透過傳遞的值阻止程式執行。